import * as React from 'react';
import { generatePath } from 'react-router-dom';
import { compose } from 'redux';
import { connect } from 'react-redux';
import styled from 'styled-components';
import { QCX } from '../../lib/QCX';
import { IStoreState } from '../../model/IStoreState';
import { Routes } from '../../app/Routing';
import { ENewsItemCoverTypes, ENewsTypes, INewsItem } from '../../model/INewsList';
import { renderDate } from '../../screen/news-item-detailed-screen/NewsItemDetailedScreen';
import { IconsFactoryContext } from '../../app/IconsFactory';
import { i18n } from '../../utils/I18n';
import { NewsItemCover } from './cover/NewsItemCover';
import { quizWithRouter as withRouter } from '@flavour/lib/quizWithRouter';
import { AudioPlayerWithCover } from '../../components/audio-player/AudioPlayerWithCover';
import { ReduxModule } from '../../store/ReduxModule';
import { NewsReactionCounter } from '../lesson/reaction-counter/NewsReactionCounter';
import { EReactionType } from '../../model/IReactions';
import { QuizlabThemeSelector } from '../theme/QuizlabThemeSelector';
import { QuizColor } from '@flavour/lib/color/QuizColor';
import { ComponentsFactoryContext } from '@flavour/app/ComponentsFactoryContext';
import { FlavourName } from '@flavour/model/IFlavour';

const classNameBasic = 'news-item';
const qcx = QCX.bindCX(require('./NewsItem.scss'), classNameBasic);

function findAncestor(el, sel, untilEl) {
    while ((el = el.parentElement) && el !== untilEl && !((el.matches || el.matchesSelector).call(el, sel)));
    return el;
}

interface OwnProps {
    newsId?: string;
    online?: boolean;
    onClickNewsItemAndChangeContext?: (newsId: number) => {};
}

interface StateToProps {
    newsItem?: INewsItem;
    playerReactionType?: EReactionType;
    flavourName?: FlavourName;
}

interface WithRouterProps {
    history?: string[];
}

interface DispatchToProps {
    onImageClick?: () => void;
    saveCurrentTime?: (value: number) => void;
    sendReaction?: (type: EReactionType.LIKE | EReactionType.DISLIKE) => void;
}

interface Props extends StateToProps, OwnProps, DispatchToProps, WithRouterProps {}

const NewsItemContentThemed = styled.div`
    border-color: ${(props) => QuizColor.rgba(QuizlabThemeSelector.getButtonBorderColor(props), 0.08)};
    border-radius: ${(props) => props.theme.borderRadiusL};
`;

const NewsItemShowMore = styled.div`
    color: ${(props) => QuizlabThemeSelector.getActiveElementsBackgroundColor(props)};
`;

const NewsItemReactionIconWrap = styled.div<{
    mode: 'like' | 'dislike',
    selected?: boolean
}>`
    svg {
        fill: ${props => 
            props.selected
                ? props.mode == 'like'
                    ? QuizlabThemeSelector.getGreenColor(props)
                    : QuizlabThemeSelector.getRedColor(props)
                : 'none'
        };
        stroke: ${props =>
            props.selected
                ? props.mode == 'like'
                    ? QuizlabThemeSelector.getGreenColor(props)
                    : QuizlabThemeSelector.getRedColor(props)
                : QuizlabThemeSelector.getBlackColor(props)
        };
    }
`

export const NewsItemComponent = (props: Props) => {
    const { newsItem, onImageClick, newsId, online, history, flavourName } = props;
    const { duration, title, upload, image, type } = { ...newsItem.cover };

    const newsTextContent = (
        <ComponentsFactoryContext.Factory.NewsRichTextWithVideo
            newsItem={newsItem}
            className={classNameBasic}
            onImageClick={onImageClick}
            online={online}
            dataUnitId={newsId}
        />
    );

    const typesOfNewsCard = {
        audio: type == ENewsItemCoverTypes.AUDIO,
        titleText:
            !newsItem.cover &&
            !(newsItem.text?.substring(1, 51) == `p class="mce-p_full-widthed mceNonEditable"><quiz-`) &&
            !(newsItem.text && newsItem.text?.substring(1, 7) == `p><img`),
        titleCover: !newsItem.text,
        titleVideoInText:
            !newsItem.cover &&
            newsItem.videoData &&
            newsItem.text?.substring(1, 51) == `p class="mce-p_full-widthed mceNonEditable"><quiz-`,
        titleImageInText: !newsItem.cover && newsItem.text && newsItem.text?.substring(1, 7) == `p><img`,
    };
    const newsCardType = Object.keys(typesOfNewsCard).filter((type) => {
        return typesOfNewsCard[type] === true;
    });
    const renderHeader = () => {
        return <div className={qcx('__header')}>{newsItem.header}</div>;
    };

    const renderNewsCardView = () => {
        switch (newsCardType[0]) {
            case 'titleText':
                return (
                    <>
                        {renderHeader()}
                        {renderText(false, false)}
                    </>
                );
            case 'titleCover':
                return (
                    <>
                        <NewsItemCover newsItemId={props.newsId} />
                        {renderHeader()}
                    </>
                );
            case 'titleImageInText':
                return (
                    <>
                        {renderHeader()}
                        {renderText(true, false)}
                    </>
                );
            case 'titleVideoInText':
                return (
                    <>
                        {renderHeader()}
                        {renderText(true, true)}
                    </>
                );
            case 'audio':
                return <>
                    {renderHeader()}
                    <AudioPlayerWithCover
                        onSaveCurrentTime={props.saveCurrentTime}
                        currentTime={newsItem.currentTime}
                        audio={{
                            author: newsItem.text,
                            date: renderDate(newsItem.createdAt),
                            duration,
                            title,
                            upload,
                            image,
                        }}
                    />
                </>
            default:
                return (
                    <>
                        <NewsItemCover newsItemId={props.newsId} />
                        {renderHeader()}
                        {renderText(false, false)}
                    </>
                );
        }
    };

    const renderText = (showMedia, isMediaVideo): React.ReactNode => {
        return (
            <div
                className={qcx('__news-description', {
                    '__news-description_with-media': showMedia,
                    '__news-description_with-media_video': isMediaVideo,
                })}
            >
                <div>{newsTextContent}</div>
                <div
                    className={qcx('__news-description_overlay', {
                        '__news-description_overlay_hidden': showMedia || newsItem.text?.length < 150,
                    })}
                ></div>
            </div>
        );
    };

    const renderReactions = () => {
        if (!newsItem.reactions) return;

        return (
            <div className={qcx('__reactions')}>
                <div className={qcx('__reaction')}>
                    <NewsItemReactionIconWrap
                        mode='like'
                        selected={props.playerReactionType == EReactionType.LIKE}
                        className={qcx('__reaction-icon', '__reaction-icon_like', {
                            '__reaction-icon_selected': props.playerReactionType == EReactionType.LIKE,
                        })}
                        onClick={(e) => {
                            e.stopPropagation();
                            e.preventDefault();
                            props.sendReaction( EReactionType.LIKE);
                        }}
                    >
                        <IconsFactoryContext.Factory.ThumbsUpIcon />
                    </NewsItemReactionIconWrap>
                    <div className={qcx('__reaction-count')}>
                        <NewsReactionCounter reactionType={EReactionType.LIKE} newsId={newsItem.id} />
                    </div>
                </div>
                <div className={qcx('__reaction')}>
                    <NewsItemReactionIconWrap
                        mode='dislike'
                        selected={props.playerReactionType == EReactionType.DISLIKE}
                        className={qcx('__reaction-icon', '__reaction-icon_dislike', {
                            '__reaction-icon_selected': props.playerReactionType == EReactionType.DISLIKE,
                        })}
                        onClick={(e) => {
                            e.stopPropagation();
                            e.preventDefault();
                            props.sendReaction( EReactionType.DISLIKE);
                        }}
                    >
                        <IconsFactoryContext.Factory.ThumbsDownIcon />
                    </NewsItemReactionIconWrap>
                    <div className={qcx('__reaction-count')}>
                        <NewsReactionCounter reactionType={EReactionType.DISLIKE} newsId={newsItem.id} />
                    </div>
                </div>
            </div>
        );
    };

    const handleClickCapture = React.useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        const hasCoverVideo = Boolean(
            [...e.currentTarget.children[0].children].filter((node) =>
                node.classList.contains('news-item-cover_video'),
            ).length,
        );
        const hasTextVideo = Boolean(
            [...e.currentTarget.children[0].children].filter((node) =>
                node.classList.contains('news-item__news-description_with-media_video'),
            ).length,
        );
        const isClickedOnReaction =
            (e.target as Element).parentElement.parentElement.classList.contains('news-item__reaction') ||
            (e.target as Element).parentElement.classList.contains('news-item__reaction') ||
            (e.target as Element).classList.contains('news-item__reaction');

        const isVideo =
            (hasCoverVideo || hasTextVideo) &&
            ((e.target as Element).classList?.contains('video-poster__fade') ||
                !(e.target as Element).classList.length);

        const hasAudio = newsCardType[0] == 'audio' && Boolean(
            findAncestor(e.target, '.audio-player-with-cover', e.currentTarget) !== e.currentTarget
        );

        if (isVideo || isClickedOnReaction || hasAudio) {
            return;
        } else {
            window.location.hash = generatePath(Routes.NEWS_ITEM, { newsId: newsId });
            props.onClickNewsItemAndChangeContext(Number(newsId));
            return;
        }
    }, [
        props.onClickNewsItemAndChangeContext
    ])

    const handleOnClickNews = (newsId) => {
        history.push(`${generatePath(Routes.NEWS_ITEM, { newsId: newsId })}`);
        props.onClickNewsItemAndChangeContext(Number(newsId));
    };

    return (
        newsItem.type == ENewsTypes.AUDIO && 
        upload && 
        image &&
        flavourName == FlavourName.SEVERSTAL
    ) ? (
        <div style={{ position: 'relative' }}>
            {newsItem.isPinned && (
                <div className={qcx('__pin')}>
                    <IconsFactoryContext.Factory.NewsPinned />
                </div>
            )}

            <AudioPlayerWithCover
                isPinned={newsItem.isPinned}
                onClick={() => handleOnClickNews(newsItem.id)}
                onSaveCurrentTime={props.saveCurrentTime}
                currentTime={newsItem.currentTime}
                audio={{
                    author: newsItem.text,
                    date: renderDate(newsItem.createdAt),
                    duration,
                    title,
                    upload,
                    image,
                }}
            />
            {renderReactions()}
        </div>
    ) : (
        <div
            className={qcx()}
            onClickCapture={handleClickCapture}
        >
            <NewsItemContentThemed className={qcx('__content')}>
                {newsItem.isPinned ? (
                    <div className={qcx('__pin')}>
                        <IconsFactoryContext.Factory.NewsPinned />
                    </div>
                ) : null}
                {renderNewsCardView()}
                {(newsItem.text?.length > 150 || newsCardType[0] !== 'titleText') &&
                    newsCardType[0] !== 'titleAudio' && (
                        <NewsItemShowMore className={qcx('__show-more')}>{i18n.getMsg('show_more')}</NewsItemShowMore>
                    )}
                <div className={qcx('__date')}>{renderDate(newsItem.createdAt)}</div>
            </NewsItemContentThemed>
            {renderReactions()}
        </div>
    );
};

const mapStateToProps = (state: IStoreState, props: OwnProps): StateToProps => {
    const newsItem = state.newsList.items[props.newsId] || {};
    const news = state.newsList.items[props.newsId] || {};
    const reactions = news.reactions || {};
    const newsDeferredReactionRequest = state.newsDeferredReactionRequestList?.items[props.newsId] || {};

    return {
        newsItem,
        flavourName: state.flavour?.name as FlavourName,
        playerReactionType: newsDeferredReactionRequest.reaction || reactions.playerReaction,
    };
};

const mergeProps = (stateProps: StateToProps, { dispatch }, ownProps: OwnProps) => {
    const newsId = ownProps.newsId;

    return {
        ...ownProps,
        ...stateProps,
        onImageClick: () => {},
        saveCurrentTime: (currentTime) => {
            dispatch(
                ReduxModule.newsList.createChangeItemByIdAction(newsId, {
                    currentTime,
                }),
            );
        },
        sendReaction( reactionType: EReactionType) {
            dispatch(
                ReduxModule.newsDeferredReactionRequestList.createChangeItemByIdAction(newsId, {
                    newsId,
                    reaction: reactionType,
                }),
            );
        },
    };
};

export const NewsItem: React.FunctionComponent<Props> = compose(
    connect(mapStateToProps, (dispatch) => ({ dispatch }), mergeProps),
    withRouter,
)(NewsItemComponent);
